#!/bin/bash

if [ -z "$1" ] ; then
    echo "GenMOOSApp_ENSTABretagne: usage: $0 [app-name] [prefix]"
    exit 0
fi

if [ -z "$2" ] ; then
    echo "GenMOOSApp_ENSTABretagne: usage: $0 [app-name] [prefix]"
    exit 0
fi

#if [ -z "$3" ] ; then
#    $3="YOUR-NAME-HERE"
#fi

mkdir $2$1
cd $2$1

cat >> CMakeLists.txt <<EOF
#--------------------------------------------------------
# The CMakeLists.txt for: $2$1
# ENSTA Bretagne Robotics - moos-ivp-enstabretagne
# Author(s): $3
#--------------------------------------------------------

SET(SRC
  ${1}.cpp
  main.cpp
)

ADD_EXECUTABLE($2$1 \${SRC})

TARGET_LINK_LIBRARIES($2$1
   \${MOOS_LIBRARIES}
   xml-documentation
   apputil
   mbutil
   m
   pthread)
EOF

cat >> ${1}.h <<EOF
/************************************************************/
/*    FILE: ${1}.h
/*    ORGN: ENSTA Bretagne Robotics - moos-ivp-enstabretagne
/*    AUTH: $3
/*    DATE: 2015
/************************************************************/

#ifndef ${1}_HEADER
#define ${1}_HEADER

#include "MOOS/libMOOS/Thirdparty/AppCasting/AppCastingMOOSApp.h"

class ${1} : public AppCastingMOOSApp
{
  public:
    ${1}();
    ~${1}() {};

  protected: // Standard MOOSApp functions to overload  
    bool OnNewMail(MOOSMSG_LIST &NewMail);
    bool Iterate();
    bool OnConnectToServer();
    bool OnStartUp();

  protected: // Standard AppCastingMOOSApp functions to overload 
    bool buildReport();
    void registerVariables();

  protected: // ${1} functions


  private: // Configuration variables


  private: // State variables

};

#endif 
EOF

cat >> main.cpp <<EOF
/************************************************************/
/*    FILE: main.cpp
/*    ORGN: ENSTA Bretagne Robotics - moos-ivp-enstabretagne
/*    AUTH: $3
/*    DATE: 2015
/************************************************************/

#include <string>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include "MBUtils.h"
#include "documentation/MOOSAppDocumentation.h"
#include "ColorParse.h"
#include "${1}.h"

using namespace std;

${1} *obj${1};

void kill_handler(int s);

int main(int argc, char *argv[])
{
  obj${1} = new ${1};

  string mission_file;
  string run_command = argv[0];
  xmldoc::MOOSAppDocumentation documentation(argv[0]);

  for(int i=1; i<argc; i++)
  {
    string argi = argv[i];
    if((argi=="-v") || (argi=="--version") || (argi=="-version"))
      documentation.showReleaseInfoAndExit();
    else if((argi=="-e") || (argi=="--example") || (argi=="-example"))
      documentation.showExampleConfigAndExit();
    else if((argi == "-h") || (argi == "--help") || (argi=="-help"))
      documentation.showHelpAndExit();
    else if((argi == "-i") || (argi == "--interface"))
      documentation.showInterfaceAndExit();
    else if(strEnds(argi, ".moos") || strEnds(argi, ".moos++"))
      mission_file = argv[i];
    else if(strBegins(argi, "--alias="))
      run_command = argi.substr(8);
    else if(i==2)
      run_command = argi;
  }

  if(mission_file == "")
    documentation.showHelpAndExit();

  cout << termColor("green");
  cout << "${2}${1} launching as " << run_command << endl;
  cout << termColor() << endl;

  // To catch the kill event
  struct sigaction sigIntHandler;
  sigIntHandler.sa_handler = kill_handler;
  sigemptyset(&sigIntHandler.sa_mask);
  sigIntHandler.sa_flags = 0;
  sigaction(SIGTERM, &sigIntHandler, NULL);
  sigaction(SIGKILL, &sigIntHandler, NULL);
  sigaction(SIGQUIT, &sigIntHandler, NULL);
  sigaction(SIGINT, &sigIntHandler, NULL);

  obj${1}->Run(run_command.c_str(), mission_file.c_str());

  return(0);
}

void kill_handler(int s)
{
  delete obj${1};
  exit(0);
}
EOF

cat >> $2${1}.moos <<EOF
//------------------------------------------------
// ${2}${1} config block

ProcessConfig = ${2}${1}
{
  AppTick   = 4
  CommsTick = 4
}
EOF

cat >> ${1}.cpp <<EOF
/************************************************************/
/*    FILE: ${1}.cpp
/*    ORGN: ENSTA Bretagne Robotics - moos-ivp-enstabretagne
/*    AUTH: $3
/*    DATE: 2015
/************************************************************/

#include <iterator>
#include "MBUtils.h"
#include "ACTable.h"
#include "${1}.h"

using namespace std;

//---------------------------------------------------------
// Constructor

${1}::${1}()
{
}

//---------------------------------------------------------
// Procedure: OnNewMail

bool ${1}::OnNewMail(MOOSMSG_LIST &NewMail)
{
  AppCastingMOOSApp::OnNewMail(NewMail);

  MOOSMSG_LIST::iterator p;
  for(p = NewMail.begin() ; p != NewMail.end() ; p++)
  {
    CMOOSMsg &msg = *p;
    string key    = msg.GetKey();

    #if 0 // Keep these around just for template
      string comm  = msg.GetCommunity();
      double dval  = msg.GetDouble();
      string sval  = msg.GetString(); 
      string msrc  = msg.GetSource();
      double mtime = msg.GetTime();
      bool   mdbl  = msg.IsDouble();
      bool   mstr  = msg.IsString();
    #endif

    if(key == "FOO") 
      cout << "great!";

    else if(key != "APPCAST_REQ") // handle by AppCastingMOOSApp
      reportRunWarning("Unhandled Mail: " + key);
  }

  return true;
}

//---------------------------------------------------------
// Procedure: OnConnectToServer

bool ${1}::OnConnectToServer()
{
  registerVariables();
  return true;
}

//---------------------------------------------------------
// Procedure: Iterate()
//            happens AppTick times per second

bool ${1}::Iterate()
{
  AppCastingMOOSApp::Iterate();

  // Do your thing here!

  AppCastingMOOSApp::PostReport();
  return true;
}

//---------------------------------------------------------
// Procedure: OnStartUp()
//            happens before connection is open

bool ${1}::OnStartUp()
{
  AppCastingMOOSApp::OnStartUp();

  STRING_LIST sParams;
  m_MissionReader.EnableVerbatimQuoting(false);
  if(!m_MissionReader.GetConfiguration(GetAppName(), sParams))
    reportConfigWarning("No config block found for " + GetAppName());

  STRING_LIST::iterator p;
  sParams.reverse();
  for(p = sParams.begin() ; p != sParams.end() ; p++)
  {
    string orig  = *p;
    string line  = *p;
    string param = toupper(biteStringX(line, '='));
    string value = line;
    bool handled = false;

    if(param == "FOO")
    {
      handled = true;
    }

    else if(param == "BAR")
    {
      handled = true;
    }

    if(!handled)
      reportUnhandledConfigWarning(orig);
  }

  registerVariables();  
  return true;
}

//---------------------------------------------------------
// Procedure: registerVariables

void ${1}::registerVariables()
{
  AppCastingMOOSApp::RegisterVariables();
  // Register("FOOBAR", 0);
}

//------------------------------------------------------------
// Procedure: buildReport()

bool ${1}::buildReport() 
{
  #if 0 // Keep these around just for template
    ACTable actab(4);
    actab << "Alpha | Bravo | Charlie | Delta";
    actab.addHeaderLines();
    actab << "one" << "two" << "three" << "four";
    m_msgs << actab.getFormattedString();
  #endif

  return true;
}
EOF


cat >> ${2}${1}.xml <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<!-- This file contains ${2}${1} documentation -->
<?xml-stylesheet href="../../../doc/xmldocumentation.css" type="text/css"?> 
<xmldoc>
  <moosapp>

     <info>
        <name>${2}${1}</name>
        <organization>ENSTA Bretagne Robotics - moos-ivp-enstabretagne</organization>
        <date>2015</date>
        <authors>
           <author>${3}</author>
        </authors>
        <licence>MIT</licence>
     </info>

     <documentation>
        <synopsis>
          ...
        </synopsis>
        <interface>
           <subscriptions>
              <!--
              <moosvar>
                 <varname>EXAMPLE_VAR_IN</varname>
                 <vartype>string</vartype>
                 <varinfo>description of the MOOSVar</varinfo>
              </moosvar>
              -->
           </subscriptions>
           <publications>
              <!--
              <moosvar>
                 <varname>EXAMPLE_VAR_OUT</varname>
                 <vartype>string</vartype>
                 <varinfo>description of the MOOSVar</varinfo>
              </moosvar>
              -->
           </publications>
        </interface>
        <!-- if there is a bug or a special fact to know.. -->
        <optional-comments>
           No comment.
        </optional-comments>
        <!-- if something can be improved -->
        <suggested-improvements>
           No suggested improvements.
        </suggested-improvements>
     </documentation>

  </moosapp>
</xmldoc>
EOF

echo "$2${1} generated."
echo "Please update src/app/CMakeLists.txt and doc/index.html files."